﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using DevelopersToolbox;

namespace TemplateTools {
    public partial class TemplateControl : UserControl, IExecutableTool {
        public TemplateControl() {
            InitializeComponent();
        }

        public void Execute() {
            try {
                string template = _template.GetDataAsString();
                Dictionary<string, string> fieldValues = FieldValues;
                string renderResults = TemplateHelper.Render(template, fieldValues);
                _result.Text = renderResults;
            } catch (Exception ex) {
                _result.Text = ex.Message;
            }
        }

        private Dictionary<string, string> FieldValues {
            get {
                if (_properties.SelectedObject != null) {
                    return ((FieldDefinitionsWrapper)_properties.SelectedObject).FieldValues;
                } else {
                    return new Dictionary<string, string>();
                }
            }
        }

        private void _go_Click(object sender, EventArgs e) {
            Execute();
        }

        private void _template_DataChanged(object sender, EventArgs e) {
            try {
                string template = _template.GetDataAsString();
                TemplateFieldDefinition[] fieldDefinitions = TemplateHelper.GetFieldDefinitions(template);
                _properties.SelectedObject = new FieldDefinitionsWrapper(fieldDefinitions, FieldValues);
                _message.Text = "Template OK";
            } catch (Exception ex) {
                _message.Text = ex.Message;
            }
        }

        private class FieldDefinitionsWrapper : ICustomTypeDescriptor {
            private readonly TemplateFieldDefinition[] _fieldDefinitions;
            private readonly PropertyDescriptorCollection _propertyDescriptorCollection;
            private readonly Dictionary<string, string> _fieldValues;

            public FieldDefinitionsWrapper(TemplateFieldDefinition[] fieldDefinitions, Dictionary<string, string> fieldValues) {
                _fieldValues = fieldValues;
                _fieldDefinitions = fieldDefinitions;
                PropertyDescriptor[] properties = _fieldDefinitions.Select(fd => new FieldDefinitionPropertyDescriptor(fd)).ToArray();
                _propertyDescriptorCollection = new PropertyDescriptorCollection(properties);
            }

            public Dictionary<string, string> FieldValues {
                get {
                    return _fieldValues;
                }
            }

            public AttributeCollection GetAttributes() {
                return null;
            }

            public string GetClassName() {
                return "TemplateFields";
            }

            public string GetComponentName() {
                return "TemplateFields";
            }

            public TypeConverter GetConverter() {
                return null;
            }

            public EventDescriptor GetDefaultEvent() {
                return null;
            }

            public PropertyDescriptor GetDefaultProperty() {
                return null;
            }

            public object GetEditor(Type editorBaseType) {
                return null;
            }

            public EventDescriptorCollection GetEvents() {
                return null;
            }

            public EventDescriptorCollection GetEvents(Attribute[] attributes) {
                return null;
            }

            public PropertyDescriptorCollection GetProperties() {
                return _propertyDescriptorCollection;
            }

            public PropertyDescriptorCollection GetProperties(Attribute[] attributes) {
                return GetProperties();
            }

            public object GetPropertyOwner(PropertyDescriptor pd) {
                return this;
            }

            public object GetValue(string fieldName) {
                string value;
                if (_fieldValues.TryGetValue(fieldName, out value)) {
                    return value;
                }
                return null;
            }

            public void SetValue(string fieldName, string value) {
                _fieldValues[fieldName] = value;
            }
        }

        private class FieldDefinitionPropertyDescriptor : PropertyDescriptor {
            public FieldDefinitionPropertyDescriptor(TemplateFieldDefinition fieldDefinition)
                : base(fieldDefinition.Name, GetAttributes(fieldDefinition)) {
            }

            private static Attribute[] GetAttributes(TemplateFieldDefinition fieldDefinition) {
                return new Attribute[] { };
            }

            public override bool CanResetValue(object component) {
                return true;
            }

            public override object GetValue(object component) {
                return ((FieldDefinitionsWrapper)component).GetValue(Name);
            }

            public override void ResetValue(object component) {
                SetValue(component, "");
            }

            public override void SetValue(object component, object value) {
                ((FieldDefinitionsWrapper)component).SetValue(Name, (string)value);
            }

            public override bool ShouldSerializeValue(object component) {
                return false;
            }

            public override Type ComponentType {
                get { return typeof(string); }
            }

            public override bool IsReadOnly {
                get { return false; }
            }

            public override Type PropertyType {
                get { return typeof(string); }
            }
        }
    }
}
